package com.jingdianjichi.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import com.jingdianjichi.auth.common.constant.AuthPrefix;
import com.jingdianjichi.auth.common.enums.AuthUserStatusEnum;
import com.jingdianjichi.auth.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.auth.domain.constant.AuthConstant;
import com.jingdianjichi.auth.domain.convert.AuthUserConverter;
import com.jingdianjichi.auth.domain.entity.AuthUserBO;
import com.jingdianjichi.auth.domain.redis.RedisUtil;
import com.jingdianjichi.auth.domain.service.AuthUserDomainService;
import com.jingdianjichi.auth.infra.basic.entity.*;
import com.jingdianjichi.auth.infra.basic.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private AuthPermissionService authPermissionService;

    private static final String SAULT = "chicken";
    private static final String LOGIN_PREFIX = "loginCode";
    @Resource
    private RedisUtil redisUtil;

    public Boolean checkExist(String userName) {
        AuthUser authUserCheck = new AuthUser();
        authUserCheck.setUserName(userName);
        authUserCheck.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<AuthUser> authUserList = authUserService.queryByCondition(authUserCheck);
        if (authUserList != null && authUserList.size() > 0) {
            return false;
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBOToAuthUser(authUserBO);
        // 校验用户是否存在
        if (!checkExist(authUserBO.getUserName())) {
            return false;
        }
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
//        md5摘要加密
        if (!StringUtils.isBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), SAULT));
        }
        Integer count = authUserService.insert(authUser);

        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        Integer roleId = roleResult.getId();

        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(authUser.getId());
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        AuthUserRole insertResult = authUserRoleService.insert(authUserRole);

//      auth.role.authUser.getUserName作为key
//      往redis里写入role
        String roleKey = redisUtil.buildKey(AuthPrefix.AUTH_ROLE_PREFIX, authUser.getUserName());
        /*List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));*/
        List<String> roleKeyList = new LinkedList<>();
        roleKeyList.add(authRole.getRoleKey());
        redisUtil.set(roleKey, new Gson().toJson(roleKeyList));

        //      往redis里写入permission
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> authRolePermissionList =
                authRolePermissionService.queryByCondition(authRolePermission);
        List<Integer> permissionIdList = authRolePermissionList.stream().
                map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        List<AuthPermission> authPermissionList = authPermissionService.batchQueryByPermissionIdList(permissionIdList);
        String permissionKey = redisUtil.buildKey(AuthPrefix.AUTH_PERMISSION_PREFIX, authUser.getUserName());
//        redisUtil.set(permissionKey, new Gson().toJson(authPermissionList));
        List<String> permissionKeyList = authPermissionList.stream().
                map(AuthPermission::getPermissionKey).collect(Collectors.toList());
        redisUtil.set(permissionKey, new Gson().toJson(permissionKeyList));
        return count > 0;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBOToAuthUser(authUserBO);
        Integer result = authUserService.update(authUser);
        return result > 0;
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        authUser.setId(authUserBO.getId());
        Integer result = authUserService.update(authUser);
        return result > 0;
    }

    @Override
    public Boolean changeStatus(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setStatus(authUserBO.getStatus());
        Integer result = authUserService.update(authUser);
        return result > 0;
    }

    @Override
    public SaTokenInfo deLogin(String captcha) {
        String key = redisUtil.buildKey(LOGIN_PREFIX, captcha);
        String openId = redisUtil.get(key);
        if (StringUtils.isBlank(openId)) return null;
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        // 用户存在则自动登录，不存在就先自动注册然后登陆
        this.register(authUserBO);
        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        List<AuthUser> authUsers = authUserService.queryByCondition(authUser);
        if (CollectionUtils.isEmpty(authUsers)) {
            return null;
        }
        AuthUserBO user = AuthUserConverter.INSTANCE.convertAuthUserToBO(authUsers.get(0));
        return user;
    }
}
